package com.huiquan.analysis.service;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.huiquan.analysis.dao.AnalysisOutsourcingDao;
import com.huiquan.foundation.util.BusinessUtil;
import com.huiquan.framework.utils.FileUtils;

@Service
public class AnalysisOutsourcingService {

	private static final Logger LOG = LoggerFactory.getLogger(AnalysisOutsourcingService.class);

	@Value("${init.temp.sentence.path}")
	private String tempSentencePath;
	@Value("${init.temp.split.script}")
	private String splitTempScript;
	@Value("${init.temp.result.path}")
	private String tempResultPath;
	@Value("${init.temp.pre.label.path}")
	private String tempPreLabelPath;
	@Value("${init.temp.label.script}")
	private String tempLabelScript;
	@Value("${init.temp.result.sid.path}")
	private String tempResultSidPath;
	@Value("${init.temp.result.sid.script}")
	private String tempResultSidScript;

	@Autowired
	private AnalysisOutsourcingDao analysisOutsourcingDao;

	public void initSentence() throws Exception {
		// 获取句子ID和句子
		List<Map<String, Object>> list = analysisOutsourcingDao.retrieveSidAndSentence();

		LOG.info("Get sid and sentence success, size=" + list.size());

		if (list != null && !list.isEmpty()) {
			StringBuilder sb = new StringBuilder();
			for (Map<String, Object> map : list) {
				sb.append(map.get("sentence"));
				sb.append("\n");
			}
			String path = BusinessUtil.getCompletePath4Properties(tempSentencePath);
			FileUtils.generateFile(path, sb.toString());
			LOG.info("创建预处理输入文件成功!");

			// 分词
			BusinessUtil.excuteShell(new String[] { splitTempScript });

			// 将分词结果加上sid插入到数据库
			List<Map<String, Object>> vocabularys = batchInsertVocabularys(list);
			LOG.info("分词入库成功，size=" + vocabularys.size());

			initLabelSentence(vocabularys);
		}
		LOG.info("预标注处理结束");

	}

	public void initLabelSentence() throws Exception {

		List<Map<String, Object>> vocabularys = analysisOutsourcingDao.retrieveTempVocabularys();
		LOG.info("获取分词成功，size=" + vocabularys.size());

		initLabelSentence(vocabularys);
	}

	private void initLabelSentence(List<Map<String, Object>> vocabularys) throws Exception {

		// 计算句子的词语覆盖率
		setVocabExists(vocabularys);
		LOG.info("词语覆盖率计算成功");

		// 将覆盖率靠后的选出一定数量进行预标注
		labelByExists();
	}

	private void labelByExists() throws Exception {
		// 获取排序靠前的数据
		List<Map<String, Object>> vocabs = analysisOutsourcingDao.retrieveVocabularysByExists();

		StringBuffer sb = new StringBuffer();
		Long sid, sidTemp = 0L;
		for (Map<String, Object> vocab : vocabs) {
			sid = (Long) vocab.get("sid");
			if (!sid.equals(sidTemp)) {
				if (!sidTemp.equals(0L)) {
					sb.append("\n");
				}
				sidTemp = sid;
			}
			sb.append(vocab.get("vocabulary"));
			sb.append("\t");
			sb.append(vocab.get("characteristic"));
			sb.append("\n");
		}
		String path = BusinessUtil.getCompletePath4Properties(tempPreLabelPath);
		FileUtils.generateFile(path, sb.toString());

		BusinessUtil.excuteShell(new String[] { tempLabelScript });
	}

	private void setVocabExists(List<Map<String, Object>> vocabularys) {

		// 获取当前已标注的所有词语
		List<String> vs = analysisOutsourcingDao.retrieveBankVocabularys();
		List<String> vs2 = analysisOutsourcingDao.retrieveOriginalVocabularys();
		vs.addAll(vs2);

		// 根据sid来获取每个句子的未校验分数
		Long sid = 0L;
		int sum = 0, existsNum = 0;
		List<Map<String, Object>> result = new ArrayList<>();
		for (Map<String, Object> usedVocabulary : vocabularys) {
			Long usedSid = (Long) usedVocabulary.get("sid");
			String vocab = (String) usedVocabulary.get("vocabulary");

			if (!usedSid.equals(sid)) {
				// 更新sid，换了句子，需要记录上一个句子的分值
				if (sid != 0) {
					Map<String, Object> sentence = new HashMap<>();
					sentence.put("sid", sid);
					sentence.put("sum", sum);
					sentence.put("existsNum", existsNum);
					if (sum == 0) {
						sentence.put("score", 1);
					} else {
						sentence.put("score", existsNum * 1.0 / sum);
					}
					result.add(sentence);
				}

				sid = usedSid;
				sum = 0;
				existsNum = 0;
			}

			// 一些词语不需要进入计算
			String regex = ".*(年|月|日|\\p{Digit}|\\p{Punct}|\\p{Blank}).*";
			Matcher m = Pattern.compile(regex).matcher(vocab);
			if (!m.matches()) {
				sum++;
				if (vs.contains(vocab)) {
					existsNum++;
				}
			}
		}

		Map<String, Object> sentence = new HashMap<>();
		sentence.put("sid", sid);
		sentence.put("sum", sum);
		sentence.put("existsNum", existsNum);
		sentence.put("score", existsNum * 1.0 / sum);
		result.add(sentence);

		// 将结果记录在临时表中
		analysisOutsourcingDao.deleteVocabExists();
		analysisOutsourcingDao.batchInsertVocabExists(result);
	}

	private List<Map<String, Object>> batchInsertVocabularys(List<Map<String, Object>> list) throws Exception {
		// 返回sid对应词语的结果
		List<Map<String, Object>> sidVocabs = new ArrayList<>();

		// 获取分词结果
		String path = BusinessUtil.getCompletePath4Properties(tempResultPath);
		File resultFile = new File(path);
		InputStreamReader read = new InputStreamReader(new FileInputStream(resultFile), "UTF-8");// 考虑到编码格式

		// 根据分词结果获取需要预标注的sid和词语
		BufferedReader bufferedReader = new BufferedReader(read);

		String lineTxt = null;
		int count = 0;
		Long sid, sidTemp = 0L;
		String vocabulary, characteristic;
		Map<String, Object> sidVocab;
		String[] tempVs;

		StringBuffer sb = new StringBuffer();
		while ((lineTxt = bufferedReader.readLine()) != null) {
			if ("".equals(lineTxt.trim())) {
				count++;
			} else {
				sid = (Long) list.get(count).get("id");
				tempVs = lineTxt.split("\t");
				vocabulary = tempVs[0];
				characteristic = tempVs[1];

				if (!sid.equals(sidTemp)) {
					if (!sidTemp.equals(0L)) {
						sb.append("\n");
					}
					sidTemp = sid;
				}
				sb.append(sid);
				sb.append("\t");
				sb.append(vocabulary);
				sb.append("\t");
				sb.append(characteristic);
				sb.append("\n");

				// 维护需要返回的值
				sidVocab = new HashMap<>();
				sidVocab.put("sid", sid);
				sidVocab.put("vocabulary", vocabulary);
				sidVocab.put("characteristic", characteristic);
				sidVocabs.add(sidVocab);
			}
		}
		String sidPath = BusinessUtil.getCompletePath4Properties(tempResultSidPath);
		FileUtils.generateFile(sidPath, sb.toString());

		// 调用脚本将数据加入到数据库
		BusinessUtil.excuteShell(new String[] { tempResultSidScript });

		read.close();

		return sidVocabs;
	}
}
